// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "memento_common.h"
#include "diskimage_installer.h"
#include <gtest/gtest.h>

#include <stdlib.h>
#include <stdio.h>

#include <string>
#include <sstream>

using std::string;
using std::stringstream;

namespace chromeos_memento_updater {

const string kProgramDir = ".";
const string kFakeImagePath = "faketestimage.bin";
const string kFakeZipImagePath = "faketestimage.bin.zip";
const string kTestString = "DiskImageInstallerTest Passed!\n";

class DiskImageInstallerTest : public ::testing::Test {
 protected:
  DiskImageInstallerTest()
    : installer_(kProgramDir, string(), kFakeImagePath, kImage),
      zip_installer_(kProgramDir, string(), kFakeZipImagePath, kZip) {

    const int kBlockSize = 512;
    const int kOffset = 50;
    const int kTotalBlocks = 10000;
    const int kTestBlocks = 100;
    // Touch the temp file
    FILE* fp = fopen(kFakeImagePath.c_str(), "w");
    fclose(fp);
    // dd for /dev/zero to create enough space
    stringstream command;
    command << "dd if=/dev/zero of=" << kFakeImagePath << " bs=" <<
               kBlockSize << " count=" << kTotalBlocks;
    system_call(command.str(), "Failed to create empty trunks");
    // Create cgpt header
    system_call("cgpt create " + kFakeImagePath,
                "Failed to run cgpt create");
    command.str(string());
    command << "cgpt add -b" << kOffset << " -s " << kTestBlocks <<
               " -t data " << kFakeImagePath;
    system_call(command.str(), "Failed to run cgpt add");
    // Write the test string
    fp = fopen(kFakeImagePath.c_str(), "r+");
    fseek(fp, kOffset * kBlockSize, SEEK_SET);
    fwrite(kTestString.c_str(), kTestString.length(), 1, fp);
    fclose(fp);
    // Create the zipped file
    system_call("zip " + kFakeZipImagePath + " " + kFakeImagePath,
                "Failed to create zip image");
  }
  ~DiskImageInstallerTest() {
    remove(kFakeImagePath.c_str());
  }
  DiskImageInstaller installer_;
  DiskImageInstaller zip_installer_;
};


TEST_F(DiskImageInstallerTest, PrepareImage) {
  TempfileHandler handler;
  string file_path = handler.GetFilePath();
  FILE* fp = fopen(file_path.c_str(), "w");

  ASSERT_TRUE(installer_.PrepareImage(1, fp) == 0);
  fclose(fp);
  fp = fopen(file_path.c_str(), "r");
  char buffer[kTestString.length()];
  fread(buffer, kTestString.length(), 1, fp);
  EXPECT_TRUE(kTestString.compare(buffer) == 0);
  fclose(fp);
}

TEST_F(DiskImageInstallerTest, PrepareZipImage) {
  TempfileHandler handler;
  string file_path = handler.GetFilePath();
  FILE* fp = fopen(file_path.c_str(), "w");
  zip_installer_.PrepareImage(1, fp);
  fclose(fp);
  fp = fopen(file_path.c_str(), "r");
  char buffer[kTestString.length()];
  fread(buffer, kTestString.length(), 1, fp);
  EXPECT_TRUE(kTestString.compare(buffer) == 0);
  fclose(fp);
}

TEST_F(DiskImageInstallerTest, InstallDevice) {
  TempfileHandler handler;
  string file_path = handler.GetFilePath();
  installer_.InstallDevice(1, file_path, string());
  FILE* fp = fopen(file_path.c_str(), "r");
  char buffer[kTestString.length()];
  fread(buffer, kTestString.length(), 1, fp);
  fprintf(stderr, "%s\n", buffer);
  EXPECT_TRUE(kTestString.compare(buffer) == 0);
  fclose(fp);
}

}

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
